using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Tilemaps;
using DG.Tweening;

[RequireComponent(typeof(Rigidbody2D))]
public class PlayerController : MonoBehaviour {
	public enum State {
		IDLE, MOVE, ATTACK
	}
	public SpriteRenderer playerSR;
	public Transform axeTransform;
	public float actionTime = 0.25f;
	public float smoothTime = 0.25f;
	public AnimationCurve accelerationCurve = AnimationCurve.EaseInOut(0, 0, 1, 1);
	public float atkTime = 0.5f;
	public LayerMask moveMask;

	private Vector2 m_inputDirection;

	private Grid m_grid;
	private Rigidbody2D m_rb;
	private Vector2 m_moveStartPos;
	private Vector3Int m_targetCell;
	private Vector2 m_targetWorldPos;
	private float m_actionTimer;
	private float m_moveElapsedTime;
	private State m_state;
	private Tween m_atkTween;

	[Header("Pickaxe")]
	public Pickaxe mainPickaxe;
	public Pickaxe vicePickaxe;
	private SpriteRenderer m_pickaxeSpr;

	private void Awake() {
		m_rb = GetComponent<Rigidbody2D>();

		m_pickaxeSpr = axeTransform.GetComponentInChildren<SpriteRenderer>();
		m_pickaxeSpr.sprite = mainPickaxe.sprite;
		;

		m_grid = GetComponentInParent<Grid>();
		if (m_grid == null) {
			Debug.LogError("No Grid component found in scene!");
			return;
		}

		m_targetCell = m_grid.WorldToCell(transform.position);
		m_targetWorldPos = m_grid.GetCellCenterWorld(m_targetCell);
	}

	private void Update() {
		m_inputDirection = GetFilteredInput();

		if (Input.GetKeyDown(KeyCode.K)) {
			TrySwitchPickaxe();
		}
	}

	private void FixedUpdate() {
		if (m_actionTimer > 0f) {
			m_actionTimer -= Time.deltaTime;
			if (m_actionTimer <= 0f) {
				m_actionTimer = 0f;
			}
		}

		if (m_state == State.IDLE) {
			if (m_inputDirection != Vector2.zero) {
				if (TakeAction()) {
					TryStartMovement(m_inputDirection);
				}
			}
		} else if (m_state == State.MOVE) {
			SmoothMovement();
		}
	}

	private Vector2 GetFilteredInput() {
		var inputDirection = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical"));

		// 确保只朝一个方向移动
		if (Mathf.Abs(inputDirection.x) > Mathf.Abs(inputDirection.y)) {
			inputDirection.y = 0;
		} else {
			inputDirection.x = 0;
		}

		return inputDirection;
	}

	private void TrySwitchPickaxe() {
		if (vicePickaxe == null) { return; }

		(mainPickaxe, vicePickaxe) = (vicePickaxe, mainPickaxe);
		m_pickaxeSpr.sprite = mainPickaxe.sprite;

		UpdatePickAxeUI();
	}

	private void UpdatePickAxeUI() {
		
	}

	private void TryAttack(HealthProp healthProp) {
		if (m_state != State.IDLE) {
			return;
		}
		if (PlayerProp.Instance.endurance <= 0) {
			PopupTipManager.Instance.ShowTextTip("I am so tired...");
			return;
		}

		if (healthProp.type == HealthProp.Type.Rock) {
			mainPickaxe.Collect(healthProp);
		} else {
			mainPickaxe.Attack(healthProp);
		}


		m_state = State.ATTACK;

		var seq = DOTween.Sequence();
		var shake = axeTransform.DOShakePosition(0.4f, 0.2f);
		seq.Join(shake);
		seq.AppendCallback(() => {
			m_state = State.IDLE;
		});
	}

	private void TryStartMovement(Vector2 direction) {
		m_moveElapsedTime = 0;

		var moveDirection = new Vector3Int((int)direction.x, (int)direction.y, 0);
		var newTargetCell = m_targetCell + moveDirection;
		if (direction.x != 0) {
			playerSR.flipX = direction.x > 0;
			axeTransform.transform.SetLocalScaleX(-Mathf.Sign(direction.x));
		}

		if (!IsCellWalkable(newTargetCell)) {
			return;
		}

		Vector2 newTargetWorldPos = m_grid.GetCellCenterWorld(newTargetCell);
		var collider = Physics2D.OverlapPoint(newTargetWorldPos, moveMask);
		if (collider) {
			var healthProp = collider.GetComponentInChildren<HealthProp>();
			var shelf = collider.GetComponent<Shelf>();
			if (healthProp) {
				TryAttack(healthProp);
				return;
			}
			
			if (shelf)
			{
				TryBuy(shelf);
				return;
			}

			if (shelf == null && healthProp == null) return;
		}

		m_targetCell = newTargetCell;
		m_moveStartPos = m_rb.position;
		m_targetWorldPos = newTargetWorldPos;
		m_state = State.MOVE;
	}

	private void TryBuy(Shelf shelf)
	{
		if (m_state != State.IDLE) {
			return;
		}

		var playerInventory = PlayerProp.Instance.inventory;
		bool canBuy = false;
		// if can afford
		if (playerInventory.TryGetValue(shelf.Cost.costItem, out var value))
		{
			canBuy = value >= shelf.Cost.costAmount;
			if (canBuy)
			{
				playerInventory[shelf.Cost.costItem] -= value;
			}
		}
		// if free
		canBuy |= shelf.Cost.costAmount <= 0;
		if (canBuy)
		{
			shelf.OnBuy();
		}
	}

	private void SmoothMovement() {
		m_moveElapsedTime += Time.deltaTime;

		var progress = Mathf.Clamp01(m_moveElapsedTime / smoothTime);
		var easedProgress = accelerationCurve.Evaluate(progress);

		m_rb.MovePosition(Vector2.Lerp(m_moveStartPos, m_targetWorldPos, easedProgress));

		if (progress >= 1f) {
			m_rb.MovePosition(m_targetWorldPos);
			m_state = State.IDLE;
		}
	}

	private bool TakeAction() {
		if (m_actionTimer > 0f) {
			return false;
		}

		m_actionTimer = actionTime;
		return true;
	}

	private bool IsCellWalkable(Vector3Int cell) {
		// todo
		return true;
	}
}
